﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Markup;
using System.Windows.Media.Imaging;
using System.Windows.Data;
using System.Text;
using System.ComponentModel;
using System.Windows.Media.Effects;

namespace NczControlLibrary.Controls {
    /// <summary>
    /// 一个icon一个文字的button
    /// 这个icon可能来自image也可能来自一个path绘制
    /// </summary>
    [DefaultBindingPropertyAttribute("Text")]
    public class IconPopButton : Control {
        enum MyVisualState {
            nomal, mouseover, mouseleave, mouseleftbuttondown, mouseleftbuttonup, mouseoverforpathfill
        }
        public IconPopButton() {
            this.DefaultStyleKey = typeof(IconPopButton);
            this.Foreground = new SolidColorBrush(Colors.Gray);
            this.BorderBrush = new SolidColorBrush(Colors.Gray);
            this.Background = new SolidColorBrush(Colors.White);
            this.Fill = this.Foreground as SolidColorBrush;
            this.PopTopBarFill = this.Background as SolidColorBrush;
            this.BorderThickness = new Thickness(0);
            this.IsPathFillEnable = false;
            this.Loaded += new RoutedEventHandler(IconPopButton_Loaded);
        }

        void IconPopButton_Loaded(object sender, RoutedEventArgs e) {
            if (string.IsNullOrEmpty(this.TextBackup) || string.IsNullOrWhiteSpace(this.TextBackup))
                this.TextBackup = this.Text;
        }
        public override void OnApplyTemplate() {
            this.MouseEnter += new MouseEventHandler(RdpPopButton_MouseEnter);
            this.MouseLeave += new MouseEventHandler(RdpPopButton_MouseLeave);
            this.MouseLeftButtonDown += new MouseButtonEventHandler(RdpPopButton_MouseLeftButtonDown);
            this.MouseLeftButtonUp += new MouseButtonEventHandler(RdpPopButton_MouseLeftButtonUp);
            base.OnApplyTemplate();
        }

        void RdpPopButton_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) {
            if (!string.IsNullOrEmpty(this.IconBackup) || !string.IsNullOrWhiteSpace(this.IconBackup)) {
                if (this.IconModel) {
                    if (this.Data.ToString() == this.IconDefault || string.IsNullOrEmpty(this.IconDefault)) {
                        var path = XamlReader.Load(string.Format("<Path {0} Data='{1}'/>", "xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'", this.IconBackup)) as Path;
                        this.IconDefault = this.Data.ToString();
                        var g = path.Data;
                        path.Data = null;
                        this.Data = g;
                    } else {
                        var path = XamlReader.Load(string.Format("<Path {0} Data='{1}'/>", "xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'", this.IconDefault)) as Path;
                        var g = path.Data;
                        path.Data = null;
                        this.IconDefault = this.Data.ToString();
                        this.Data = g;
                    }
                } else {
                    if (this.ImageSource.UriSource.OriginalString == this.IconDefault) {
                        this.ImageSource.UriSource = new Uri(this.IconBackup, UriKind.RelativeOrAbsolute);
                    } else {
                        this.ImageSource.UriSource = new Uri(this.IconDefault, UriKind.RelativeOrAbsolute);
                    }
                }
            }
            if (!string.IsNullOrEmpty(TextBackup)) {
                var temp = this.Text;
                this.Text = this.TextBackup;
                this.TextBackup = temp;
            }
            if (this.ClickCommand != null)
                this.ClickCommand.Execute(ClickCommandParam ?? this);
            VisualStateManager.GoToState(this, MyVisualState.mouseleftbuttonup.ToString(), false);
        }

        void RdpPopButton_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) {
            this.PopIsOpen = !this.PopIsOpen;
            if (this.Content != null && this.Content.GetType().IsSubclassOf(typeof(FrameworkElement)) && this.PopIsOpen) {
                var x = e.GetPosition(null);
                var x2 = ((FrameworkElement)Application.Current.RootVisual).ActualHeight;
                var x3 = ((FrameworkElement)Application.Current.RootVisual).ActualWidth;
                var x4 = this.Content as FrameworkElement;
                var x5 = x4.ActualWidth < 1 ? x4.Width : x4.ActualWidth;
                var x6 = x4.ActualHeight < 1 ? x4.Height : x4.ActualHeight;
                if (x.X >= x3 / 2) {
                    x4.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
                    x4.VerticalAlignment = x4.VerticalAlignment;
                    x4.Margin = new Thickness { Left = this.ActualWidth - x5, Right = x4.Margin.Right, Top = x4.Margin.Top, Bottom = x4.Margin.Bottom };
                } else {
                    x4.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
                    x4.VerticalAlignment = x4.VerticalAlignment;
                    x4.Margin = new Thickness { Left = x4.Margin.Left, Right = x4.Margin.Right, Top = x4.Margin.Top, Bottom = x4.Margin.Bottom };
                }
                if (x.Y >= x2 / 2) {
                    x4.HorizontalAlignment = x4.HorizontalAlignment;
                    x4.VerticalAlignment = System.Windows.VerticalAlignment.Top;
                    x4.Margin = new Thickness { Left = x4.Margin.Left, Right = x4.Margin.Right, Top = -this.ActualHeight - x6 - this.PopTopBarDistance, Bottom = x4.Margin.Bottom };
                } else {
                    x4.HorizontalAlignment = x4.HorizontalAlignment;
                    x4.VerticalAlignment = System.Windows.VerticalAlignment.Top;
                    x4.Margin = new Thickness { Left = x4.Margin.Left, Right = x4.Margin.Right, Top = x4.Margin.Top, Bottom = x4.Margin.Bottom };

                }
            }
            VisualStateManager.GoToState(this, MyVisualState.mouseleftbuttondown.ToString(), false);
        }
        /// <summary>
        /// 用户按下按钮事件
        /// </summary>
        public event MouseButtonEventHandler eClick { add { this.MouseLeftButtonUp += value; } remove { this.MouseLeftButtonUp -= value; } }
        public void ClosePopupWindow() {
            if (this.PopIsOpen) {
                this.PopIsOpen = false;
                VisualStateManager.GoToState(this, MyVisualState.nomal.ToString(), false);
                VisualStateManager.GoToState(this, MyVisualState.mouseleftbuttonup.ToString(), false);
            }
        }
        void RdpPopButton_MouseLeave(object sender, MouseEventArgs e) {
            VisualStateManager.GoToState(this, MyVisualState.mouseleftbuttonup.ToString(), false);
            VisualStateManager.GoToState(this, MyVisualState.nomal.ToString(), false);
            if (this.MouseLeaveCommand != null) {
                this.MouseLeaveCommand.Execute(this);
            }
        }

        void RdpPopButton_MouseEnter(object sender, MouseEventArgs e) {
            if (this.Enterground != null && this.Foreground is SolidColorBrush) {
                if (this.IsPathFillEnable) {
                    VisualStateManager.GoToState(this, MyVisualState.mouseoverforpathfill.ToString(), true);
                } else if (this.Stroke != null) {
                    VisualStateManager.GoToState(this, MyVisualState.mouseover.ToString(), true);
                }
            }
            if (this.MouseEnterCommand != null) {
                this.MouseEnterCommand.Execute(this);
            }
        }
        #region dependency properties
        public static readonly DependencyProperty PathMaxHeightProperty = DependencyProperty.Register("PathMaxHeight", typeof(double), typeof(IconPopButton), new PropertyMetadata(24d, (o, k) => {
        }));
        public double PathMaxHeight { get { return (double)this.GetValue(PathMaxHeightProperty); } set { this.SetValue(PathMaxHeightProperty, value); } }
        public static readonly DependencyProperty PathMaxWidthProperty = DependencyProperty.Register("PathMaxWidth", typeof(double), typeof(IconPopButton), new PropertyMetadata(24d, (o, k) => {
        }));
        public double PathMaxWidth { get { return (double)this.GetValue(PathMaxWidthProperty); } set { this.SetValue(PathMaxWidthProperty, value); } }
        public static readonly DependencyProperty ClickCommandParamProperty = DependencyProperty.Register("ClickCommandParam", typeof(object), typeof(IconPopButton), new PropertyMetadata(default(object), (o, k) => {
        }));
        public object ClickCommandParam { get { return (object)this.GetValue(ClickCommandParamProperty); } set { this.SetValue(ClickCommandParamProperty, value); } }
        public static readonly DependencyProperty PathHeightProperty = DependencyProperty.Register("PathHeight", typeof(double), typeof(IconPopButton), new PropertyMetadata(default(double), (o, k) => {
        }));
        public double PathHeight { get { return (double)this.GetValue(PathHeightProperty); } set { this.SetValue(PathHeightProperty, value); } }
        public static readonly DependencyProperty PathWidthProperty = DependencyProperty.Register("PathWidth", typeof(double), typeof(IconPopButton), new PropertyMetadata(default(double), (o, k) => {
        }));
        public double PathWidth { get { return (double)this.GetValue(PathWidthProperty); } set { this.SetValue(PathWidthProperty, value); } }
        public static readonly DependencyProperty StretchProperty = DependencyProperty.Register("Stretch", typeof(Stretch), typeof(IconPopButton), new PropertyMetadata(default(Stretch), (o, k) => {
        }));
        public Stretch Stretch { get { return (Stretch)this.GetValue(StretchProperty); } set { this.SetValue(StretchProperty, value); } }
        public static readonly DependencyProperty PathEffectProperty = DependencyProperty.Register("PathEffect", typeof(Effect), typeof(IconPopButton), new PropertyMetadata(default(Effect), (o, k) => {
        }));
        public Effect PathEffect { get { return (Effect)this.GetValue(PathEffectProperty); } set { this.SetValue(PathEffectProperty, value); } }
        public static readonly DependencyProperty ImageEffectProperty = DependencyProperty.Register("ImageEffect", typeof(Effect), typeof(IconPopButton), new PropertyMetadata(default(Effect), (o, k) => {
        }));
        public Effect ImageEffect { get { return (Effect)this.GetValue(ImageEffectProperty); } set { this.SetValue(ImageEffectProperty, value); } }
        public static readonly DependencyProperty ClickCommandProperty = DependencyProperty.Register("ClickCommand", typeof(ICommand), typeof(IconPopButton), new PropertyMetadata(default(ICommand), (o, k) => {
        }));
        public ICommand ClickCommand { get { return (ICommand)this.GetValue(ClickCommandProperty); } set { this.SetValue(ClickCommandProperty, value); } }
        public static readonly DependencyProperty MouseEnterCommandProperty = DependencyProperty.Register("MouseEnterCommand", typeof(ICommand), typeof(IconPopButton), new PropertyMetadata(default(ICommand), (o, k) => {
        }));
        public ICommand MouseEnterCommand { get { return (ICommand)this.GetValue(MouseEnterCommandProperty); } set { this.SetValue(MouseEnterCommandProperty, value); } }
        public static readonly DependencyProperty MouseLeaveCommandProperty = DependencyProperty.Register("MouseLeaveCommand", typeof(ICommand), typeof(IconPopButton), new PropertyMetadata(default(ICommand), (o, k) => {
        }));
        public ICommand MouseLeaveCommand { get { return (ICommand)this.GetValue(MouseLeaveCommandProperty); } set { this.SetValue(MouseLeaveCommandProperty, value); } }
        public static readonly DependencyProperty IntervalProperty = DependencyProperty.Register("Interval", typeof(double), typeof(NczControlLibrary.Controls.IconPopButton), new PropertyMetadata(default(double), (o, k) => {
        }));
        public double Interval { get { return (double)this.GetValue(IntervalProperty); } set { this.SetValue(IntervalProperty, value); } }
        public static readonly DependencyProperty PopTopBarDistanceProperty = DependencyProperty.Register("PopTopBarDistance", typeof(double), typeof(IconPopButton), new PropertyMetadata(8.00d,
(o, k) => { }));
        public double PopTopBarDistance { get { return (double)this.GetValue(PopTopBarDistanceProperty); } set { this.SetValue(PopTopBarDistanceProperty, value); } }
        public static readonly DependencyProperty FillProperty = DependencyProperty.Register("Fill", typeof(SolidColorBrush), typeof(IconPopButton), new PropertyMetadata(
(o, k) => { }));
        public SolidColorBrush Fill { get { return (SolidColorBrush)this.GetValue(FillProperty); } set { this.SetValue(FillProperty, value); } }
        public static readonly DependencyProperty CornerRadiusProperty = DependencyProperty.Register("CornerRadius", typeof(CornerRadius), typeof(IconPopButton), new PropertyMetadata(
(o, k) => { }));
        public CornerRadius CornerRadius { get { return (CornerRadius)this.GetValue(CornerRadiusProperty); } set { this.SetValue(CornerRadiusProperty, value); } }
        public static readonly DependencyProperty StrokeThicknessProperty = DependencyProperty.Register("StrokeThickness", typeof(double), typeof(IconPopButton), new PropertyMetadata(
(o, k) => { }));
        public static readonly DependencyProperty TextPaddingProperty = DependencyProperty.Register("TextPadding", typeof(Thickness), typeof(IconPopButton), new PropertyMetadata(default(Thickness), (o, k) => {
        }));
        public Thickness TextPadding { get { return (Thickness)this.GetValue(TextPaddingProperty); } set { this.SetValue(TextPaddingProperty, value); } }
        public double StrokeThickness { get { return (double)this.GetValue(StrokeThicknessProperty); } set { this.SetValue(StrokeThicknessProperty, value); } }
        public static readonly DependencyProperty StrokeProperty = DependencyProperty.Register("Stroke", typeof(SolidColorBrush), typeof(IconPopButton), new PropertyMetadata(
(o, k) => { }));
        public SolidColorBrush Stroke { get { return (SolidColorBrush)this.GetValue(StrokeProperty); } set { this.SetValue(StrokeProperty, value); } }

        public static readonly DependencyProperty ContentFlowDirectionProperty = DependencyProperty.Register("ContentFlowDirection", typeof(FlowDirection), typeof(IconPopButton), new PropertyMetadata((o, k) => {
        }));
        public FlowDirection ContentFlowDirection { get { return (FlowDirection)this.GetValue(ContentFlowDirectionProperty); } set { this.SetValue(ContentFlowDirectionProperty, value); } }
        public static readonly DependencyProperty ContentProperty = DependencyProperty.Register("Content", typeof(object), typeof(IconPopButton), new PropertyMetadata(
(o, k) => { }));
        public object Content { get { return (object)this.GetValue(ContentProperty); } set { this.SetValue(ContentProperty, value); } }
        public static readonly DependencyProperty PopTopBarFillProperty = DependencyProperty.Register("PopTopBarFill", typeof(SolidColorBrush), typeof(IconPopButton), new PropertyMetadata(new SolidColorBrush(Colors.Transparent),
(o, k) => { }));
        public SolidColorBrush PopTopBarFill { get { return (SolidColorBrush)this.GetValue(PopTopBarFillProperty); } set { this.SetValue(PopTopBarFillProperty, value); } }
        public static readonly DependencyProperty PopIsOpenProperty = DependencyProperty.Register("PopIsOpen", typeof(bool), typeof(IconPopButton), new PropertyMetadata(
(o, k) => { }));
        public bool PopIsOpen { get { return (bool)this.GetValue(PopIsOpenProperty); } set { this.SetValue(PopIsOpenProperty, value); } }
        public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(IconPopButton), new PropertyMetadata("icon pop button",
(o, k) => { }));
        public string Text { get { return (string)this.GetValue(TextProperty); } set { this.SetValue(TextProperty, value); } }
        public static readonly DependencyProperty DataProperty = DependencyProperty.Register("Data", typeof(Geometry), typeof(IconPopButton), new PropertyMetadata(
(o, k) => { }));
        public Geometry Data { get { return (Geometry)this.GetValue(DataProperty); } set { this.SetValue(DataProperty, value); } }
        public static readonly DependencyProperty PathVisibilityProperty = DependencyProperty.Register("PathVisibility", typeof(Visibility), typeof(IconPopButton), new PropertyMetadata(
        (o, k) => { }));
        internal Visibility PathVisibility { get { return (Visibility)this.GetValue(PathVisibilityProperty); } set { this.SetValue(PathVisibilityProperty, value); } }
        public static readonly DependencyProperty ImageSourceProperty = DependencyProperty.Register("ImageSource", typeof(BitmapImage), typeof(IconPopButton), new PropertyMetadata(
(o, k) => { }));
        public BitmapImage ImageSource { get { return (BitmapImage)this.GetValue(ImageSourceProperty); } set { this.SetValue(ImageSourceProperty, value); } }
        public static readonly DependencyProperty ImgVisibilityProperty = DependencyProperty.Register("ImgVisibility", typeof(Visibility), typeof(IconPopButton), new PropertyMetadata(
(o, k) => { }));
        internal Visibility ImgVisibility { get { return (Visibility)this.GetValue(ImgVisibilityProperty); } set { this.SetValue(ImgVisibilityProperty, value); } }
        /// <summary>
        /// true: show path icon
        /// false: show image icon
        /// </summary>
        public bool IconModel { get { return (Visibility)GetValue(ImgVisibilityProperty) == System.Windows.Visibility.Collapsed || (Visibility)GetValue(PathVisibilityProperty) == System.Windows.Visibility.Visible ? true : false; } set { if (value) { this.SetValue(PathVisibilityProperty, Visibility.Visible); this.SetValue(ImgVisibilityProperty, Visibility.Collapsed); } else { this.SetValue(PathVisibilityProperty, Visibility.Collapsed); this.SetValue(ImgVisibilityProperty, Visibility.Visible); } } }
        public static readonly DependencyProperty EntergroundProperty = DependencyProperty.Register("Enterground", typeof(SolidColorBrush), typeof(IconPopButton), new PropertyMetadata(new SolidColorBrush(Colors.Purple),
(o, k) => { }));
        public SolidColorBrush Enterground { get { return (SolidColorBrush)this.GetValue(EntergroundProperty); } set { this.SetValue(EntergroundProperty, value); } }
        public static readonly DependencyProperty IconBackupProperty = DependencyProperty.Register("IconBackup", typeof(string), typeof(IconPopButton), new PropertyMetadata(default(string), (o, k) => {
        }));
        /// <summary>
        /// 按下button后图标的变化值可以是一个path路径，可以是一个image的路径 类型总是string
        /// </summary>
        public string IconBackup { get { return (string)this.GetValue(IconBackupProperty); } set { this.SetValue(IconBackupProperty, value); } }
        public static readonly DependencyProperty TextBackupProperty = DependencyProperty.Register("TextBackup", typeof(string), typeof(IconPopButton), new PropertyMetadata(default(string), (o, k) => {
        }));
        /// <summary>
        /// 按下button后需要变化的文字
        /// </summary>
        public string TextBackup { get { return (string)this.GetValue(TextBackupProperty); } set { this.SetValue(TextBackupProperty, value); } }
        #endregion
        /// <summary>
        /// 配合pIconBackup一起使用完成点击切换icon的目标
        /// </summary>
        string IconDefault { get; set; }
        /// <summary>
        /// 在path模式中是否是path fill起作用，true为是 否则为path stroke起作用
        /// </summary>
        public bool IsPathFillEnable { get; set; }
        public string DataString {
            get { return this.Data.ToString(); }
            set {
                var mini = value.ToString();
                var sb = new StringBuilder();
                sb.AppendFormat("<Path {0} Data='{1}'/>", "xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'", mini);
                var pathvalue = XamlReader.Load(sb.ToString()) as System.Windows.Shapes.Path;
                var geometry = pathvalue.Data;
                //pathvalue.ClearValue(Path.DataProperty);
                pathvalue.Data = null;
                this.Data = geometry;
            }
        }
    }
}
